package cn.fsd.service.impl;

import cn.fsd.domain.*;
import cn.fsd.mapper.*;
import cn.fsd.query.BaseQuery;
import cn.fsd.query.dispatch.TransferQuery;
import cn.fsd.service.BaiduService;
import cn.fsd.service.TransferService;
import cn.fsd.vo.*;
import cn.fsd.vo.storeroom.transfer.TransferCommodityTaskVO;
import cn.hutool.core.lang.UUID;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class TransferServiceImpl implements TransferService {

//    @Autowired
//    CustomerFeignClient customerFeignClient;

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    TransferMapper transferMapper;

    @Autowired
    TaskMapper taskMapper;

    @Autowired
    StationMapper stationMapper;

    @Autowired
    StoreroomMapper storeroomMapper;

    @Autowired
    Storeroom_commodityMapper storeroom_commodityMapper;

    @Autowired
    Transfer_pathMapper transfer_pathMapper;

    @Autowired
    CommodityMapper commodityMapper;

    @Autowired
    BaiduService baiduService;

    @Override
    public Transfer findById(String id){
        return transferMapper.selectByPrimaryKey(id);
    }

    @Override
    public String add(String order_id) {
        //根据前端获取的order_id在order表中确定订单
        Order order = orderMapper.selectByPrimaryKey(order_id);
        //**********这曾经是一个openfeign测试**********
//        System.out.println("**************"+order);
        //查询订单中的商品id
        String commodity_id = order.getCommodity_id();
        //根据前端获取的order_id在task表中查询订单对应的任务单
        Task task = taskMapper.selectByOrderId(order_id);
        //根据任务单的station_id查询已经确定的分站
        Station station = stationMapper.selectByPrimaryKey(task.getStation_id());
        //获取分站地址
        String station_place = station.getStation_place();
        //通过百度地图api查询地址对应的经纬度数据
        double[] stationLocationPoint = baiduService.getGeoByAddress(station_place);
        if(stationLocationPoint==null){
            return "fail";
        }

        //遍历库房，通过(查询库房对应商品的可分配量&&百度地图api计算所确定分站地址到每个库房的距离和时间)来选择库房（策略：优先选时间最短，时间相等选距离最短）
        List<Storeroom> storeroomList = storeroomMapper.selectAll();
        int index = -1;//记录符合条件的库房下标
        double minDistance = Integer.MAX_VALUE;
        double minTime = Integer.MAX_VALUE;
        for (int i = 0; i < storeroomList.size(); i++) {
            //此时循环遍历到的库房
            Storeroom storeroom = storeroomList.get(i);
            //获取该库房id
            String storeroom_id = storeroom.getStoreroom_id();
            //根据库房id和商品id在库房_商品表中查询transferable_num
            Storeroom_commodity storeroom_commodity = storeroom_commodityMapper.selectByPrimaryKey(commodity_id, storeroom_id);
            //**********************注意判断不为空，否则调用get方法会空指针异常
            if(storeroom_commodity!=null){
                //查询库房中商品的可分配量
                Integer transferable_num = storeroom_commodity.getTransferable_num();
                //查询订单中的商品数量
                Integer commodity_num = order.getCommodity_num();
                if(transferable_num>=commodity_num){//库存充足才继续根据位置判断，否则直接跳过
                    //获取该库房地址
                    String storeroom_place = storeroom.getStoreroom_place();
                    //通过百度地图api查询地址对应的经纬度数据
                    double[] storeroomLocationPoint = baiduService.getGeoByAddress(storeroom_place);
                    if(storeroomLocationPoint==null){//分站地址无法逆编码时直接跳过
                        continue;
                    }
                    //通过百度地图api计算收货人地址到每个分站的距离和时间
                    double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), String.valueOf(storeroomLocationPoint[1]) + "," + String.valueOf(storeroomLocationPoint[0]));
                    //*************这是一个测试***************
//                    System.out.println("**********distance:"+distenceAndTime[0]+"************time:"+distenceAndTime[1]);
                    if(distenceAndTime[1]<minTime){
                        index = i;
                        minDistance = distenceAndTime[0];
                        minTime = distenceAndTime[1];
                    }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
                        index = i;
                        minDistance = distenceAndTime[0];
                        minTime = distenceAndTime[1];
                    }
                }
            }
        }
        Storeroom storeroom = storeroomList.get(index);
        //通过百度地图api查询地址对应的经纬度数据
        double[] storeroomLocationPoint = baiduService.getGeoByAddress(storeroom.getStoreroom_place());
        //根据中心库房、分站库房位置，以及途径点来进行路线规划
        String waypoints = null;
        List<List<LocationPoint>> routes = baiduService.getRoute(String.valueOf(storeroomLocationPoint[1]) + "," + String.valueOf(storeroomLocationPoint[0]), String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), waypoints);
        //添加调度单
        Transfer transfer = new Transfer();
        String transfer_id = UUID.randomUUID().toString();
        transfer.setTransfer_id(transfer_id);
        transfer.setCommodity_id(commodity_id);
        transfer.setStoreroom_id(storeroom.getStoreroom_id());
        transfer.setStation_id(station.getStation_id());
        transfer.setOrder_id(order_id);
        transfer.setPath_choice(0);//默认为0，即推荐路线
        //********以下字段需要根据需求设置*********
        transfer.setTransfer_sum(1);
        transfer.setOutbound_date(new Date());
        transfer.setTransfer_status("已调度");
        int count_trans = transferMapper.insert(transfer);
        //保存调度路径
        int count_paths = 0;
        for (int i = 0; i < routes.size(); i++) {
            List<LocationPoint> route = routes.get(i);
            if (route != null) {
                Transfer_path transfer_path = new Transfer_path();
                transfer_path.setTransfer_id(transfer_id);
                transfer_path.setPath_num(i);
                transfer_path.setPath_info(route.toString());
                int count_path = transfer_pathMapper.insert(transfer_path);
                count_paths += count_path;
            }
        }
        if(count_trans==1&&count_paths==routes.size())
            return "success";
        return "fail";
    }

    @Override
    public PageBean<Transfer> findByPage(BaseQuery query) {
        //构建结果对象
        PageBean<Transfer> pageBean = new PageBean<>();

        //开启分页
        PageHelper.startPage(query.getPageNow(),query.getPageSize());

        //分页查询得到当页的集合
        List<Transfer> transferList = transferMapper.findByPage(query);

        //创建一个分页的实体PageInfo
        PageInfo<Transfer> pageInfo = new PageInfo<>(transferList);

        pageInfo.setList(pageInfo.getList().stream().map(transfer -> {
            TransferBean bean = new TransferBean(transfer);
            bean.setStoreroom_name(storeroomMapper.selectByPrimaryKey(transfer.getStoreroom_id()).getStoreroom_name());
            bean.setStation_name(stationMapper.selectByPrimaryKey(transfer.getStation_id()).getStation_name());
            bean.setCommodity_name(commodityMapper.selectByPrimaryKey(transfer.getCommodity_id()).getCommodity_name());
            return bean;
        }).collect(Collectors.toList()));

        pageBean.setTotalRows(pageInfo.getTotal());
        pageBean.setTotalPages(pageInfo.getPages());
        pageBean.setRowData(pageInfo.getList());

        return pageBean;
    }

//    @Override
//    public String getStoreroom(String receiver_address) {
//        //通过百度地图api查询收货人地址对应的经纬度数据
//        double[] receiverLocationPoint = baiduService.getGeoByAddress(receiver_address);
//        if(receiverLocationPoint==null){
//            return null;
//        }
//
//        //遍历库房，通过百度地图api计算收货人地址到每个库房的距离和时间来选择库房（策略：优先选时间最短，时间相等选距离最短）
//        List<Storeroom> storeroomList = storeroomMapper.selectAll();
//        double minDistance = Integer.MAX_VALUE;
//        double minTime = Integer.MAX_VALUE;
//        String result = "";//待返回的库房id
//        for (int i = 0; i < storeroomList.size(); i++) {
//            //此时循环遍历到的库房
//            Storeroom storeroom = storeroomList.get(i);
//            //获取该库房id
//            String storeroom_id = storeroom.getStoreroom_id();
//            //获取该库房地址
//            String storeroom_place = storeroom.getStoreroom_place();
//            //通过百度地图api查询地址对应的经纬度数据
//            double[] storeroomLocationPoint = baiduService.getGeoByAddress(storeroom_place);
//            if(storeroomLocationPoint==null){//分站地址无法逆编码时直接跳过
//                continue;
//            }
//            //通过百度地图api计算收货人地址到每个仓库的距离和时间
//            double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(receiverLocationPoint[1]) + "," + String.valueOf(receiverLocationPoint[0]), String.valueOf(storeroomLocationPoint[1]) + "," + String.valueOf(storeroomLocationPoint[0]));
//            //*************这是一个测试***************
////            System.out.println("**********distance:"+distenceAndTime[0]+"************time:"+distenceAndTime[1]);
//            if(distenceAndTime[1]<minTime){
//                result = storeroom_id;
//                minDistance = distenceAndTime[0];
//                minTime = distenceAndTime[1];
//            }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
//                result = storeroom_id;
//                minDistance = distenceAndTime[0];
//                minTime = distenceAndTime[1];
//            }
//        }
//        return result;
//    }

    @Override
    public String getStoreroom(String receiver_address) {

        //通过百度地图api查询收货人地址对应的经纬度数据
        double[] receiverLocationPoint = baiduService.getGeoByAddress(receiver_address);
        if(receiverLocationPoint==null){
            return null;
        }

        //遍历分站，通过百度地图api计算收货人地址到每个分站的距离和时间来选择分站（策略：优先选时间最短，时间相等选距离最短）
        List<Station> stationList = stationMapper.selectAll();
        int index = -1;//记录符合条件的分站下标
        double[] stationLocationPoint = new double[2];//记录所选分站地址对应的经纬度
        double minDistance = Integer.MAX_VALUE;
        double minTime = Integer.MAX_VALUE;
        for (int j = 0; j < stationList.size(); j++) {
            //获取该分站地址
            String station_place = stationList.get(j).getStation_place();
            //通过百度地图api查询地址对应的经纬度数据
            double[] stationTempLocationPoint = baiduService.getGeoByAddress(station_place);
            if(stationTempLocationPoint==null){//分站地址无法逆编码时直接跳过
                continue;
            }
            //通过百度地图api计算收货人地址到每个分站的距离和时间
            double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(receiverLocationPoint[1]) + "," + String.valueOf(receiverLocationPoint[0]), String.valueOf(stationTempLocationPoint[1]) + "," + String.valueOf(stationTempLocationPoint[0]));
            if(distenceAndTime[1]<minTime){
                index = j;
                stationLocationPoint = stationTempLocationPoint;
                minDistance = distenceAndTime[0];
                minTime = distenceAndTime[1];
            }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
                index = j;
                stationLocationPoint = stationTempLocationPoint;
                minDistance = distenceAndTime[0];
                minTime = distenceAndTime[1];
            }
        }

        //遍历库房，通过百度地图api计算收货人地址到每个库房的距离和时间来选择库房（策略：优先选时间最短，时间相等选距离最短）
        List<Storeroom> storeroomList = storeroomMapper.selectAll();
        minDistance = Integer.MAX_VALUE;
        minTime = Integer.MAX_VALUE;
        String result = "";//待返回的库房id
        for (int j = 0; j < storeroomList.size(); j++) {
            //判断是否为中心库房
            if(storeroomList.get(j).getStoreroom_level()==0){
                //获取该库房地址
                String storeroom_place = storeroomList.get(j).getStoreroom_place();
                //通过百度地图api查询地址对应的经纬度数据
                double[] storeroomLocationPoint = baiduService.getGeoByAddress(storeroom_place);
                if(storeroomLocationPoint ==null){//分站地址无法逆编码时直接跳过
                    continue;
                }
                //通过百度地图api计算收货人地址到每个分站的距离和时间
                double[] distenceAndTime = baiduService.getDistenceAndTime(String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), String.valueOf(storeroomLocationPoint[1]) + "," + String.valueOf(storeroomLocationPoint[0]));
                if(distenceAndTime[1]<minTime){
                    result = storeroomList.get(j).getStoreroom_id();
                    minDistance = distenceAndTime[0];
                    minTime = distenceAndTime[1];
                }else if(distenceAndTime[1]==minTime&&distenceAndTime[0]<minDistance){
                    result = storeroomList.get(j).getStoreroom_id();
                    minDistance = distenceAndTime[0];
                    minTime = distenceAndTime[1];
                }
            }
        }
        return result;
    }

    @Override
    public List<PointBean> showPoint(String transfer_id){
        List<PointBean> pointList = new ArrayList<>();
        Transfer transfer = transferMapper.selectByPrimaryKey(transfer_id);
        //查询库房信息
        PointBean point_storeroom = new PointBean();
        Storeroom storeroom = storeroomMapper.selectByPrimaryKey(transfer.getStoreroom_id());
        point_storeroom.setFlag("storeroom");
        point_storeroom.setId(storeroom.getStoreroom_id());
        point_storeroom.setAddress(storeroom.getStoreroom_place());
        point_storeroom.setName(storeroom.getStoreroom_name());
        point_storeroom.setPhone(storeroom.getStoreroom_phone());
        //通过百度地图api查询地址对应的经纬度数据
        double[] storeroomLocationPoint = baiduService.getGeoByAddress(storeroom.getStoreroom_place());
        point_storeroom.setLat(String.valueOf(storeroomLocationPoint[1]));
        point_storeroom.setLng(String.valueOf(storeroomLocationPoint[0]));
        pointList.add(point_storeroom);
        //查询分站信息
        PointBean point_station = new PointBean();
        Station station = stationMapper.selectByPrimaryKey(transfer.getStation_id());
        point_station.setFlag("station_choice");
        point_station.setId(station.getStation_id());
        point_station.setAddress(station.getStation_place());
        point_station.setName(station.getStation_name());
        point_station.setPhone(station.getStation_phone());
        //通过百度地图api查询地址对应的经纬度数据
        double[] stationLocationPoint = baiduService.getGeoByAddress(station.getStation_place());
        point_station.setLat(String.valueOf(stationLocationPoint[1]));
        point_station.setLng(String.valueOf(stationLocationPoint[0]));
        pointList.add(point_station);
        return pointList;
    }

    @Override
    public PageInfo<TransferCommodityTaskVO> findByStoreroomByPage(TransferQuery query) {
        PageHelper.startPage(query.getPageNow(), query.getPageSize());
        return new PageInfo<>(transferMapper.findByStoreroomByPage(query));
    }

    @Override
    public PageInfo<TransferCommodityTaskVO> findByStationByPage(TransferQuery query) {
        PageHelper.startPage(query.getPageNow(), query.getPageSize());
        return new PageInfo<>(transferMapper.findByStationByPage(query));
    }

    @Override
    public Boolean changeStatus(Transfer transfer) {
        Transfer record = transferMapper.selectByPrimaryKey(transfer.getTransfer_id());
        record.setTransfer_status(transfer.getTransfer_status());
        transferMapper.updateByPrimaryKey(record);
        return true;
    }

    @Override
    public Transfer findByOrderId(String order_id) {
        return transferMapper.selectByOrderId(order_id);
    }

    @Override
    public Transfer_path showPath(String transfer_id) {
        Transfer transfer = transferMapper.selectByPrimaryKey(transfer_id);
        Transfer_path transfer_path = transfer_pathMapper.selectByPrimaryKey(transfer_id, transfer.getPath_choice());
        return transfer_path;
    }

    @Override
    public List<Transfer_path> showPathAll(String transfer_id) {
        Transfer transfer = transferMapper.selectByPrimaryKey(transfer_id);
        List<Transfer_path> paths = transfer_pathMapper.selectByTransferId(transfer.getTransfer_id());
        return paths;
    }

    @Override
    public String update(String transfer_id, Integer path_num) {
        Transfer transfer = transferMapper.selectByPrimaryKey(transfer_id);
        transfer.setPath_choice(path_num);
        int count = transferMapper.updateByPrimaryKey(transfer);
        if(count==1)
            return "success";
        return "fail";
    }

    @Override
    public String addWithWaypoints(String transfer_id,String waypoints) {
        Transfer transfer = transferMapper.selectByPrimaryKey(transfer_id);
        String station_place = stationMapper.selectByPrimaryKey(transfer.getStation_id()).getStation_place();
        double[] stationLocationPoint = baiduService.getGeoByAddress(station_place);
        String storeroom_place = storeroomMapper.selectByPrimaryKey(transfer.getStoreroom_id()).getStoreroom_place();
        double[] storeroomLocationPoint = baiduService.getGeoByAddress(storeroom_place);
        //由于前端传url到后端有字符规则限制，"|"为无效字符，所以在后端改成api要求的格式
        waypoints = waypoints.replaceAll(";","|");
        List<List<LocationPoint>> routes = baiduService.getRoute(String.valueOf(storeroomLocationPoint[1]) + "," + String.valueOf(storeroomLocationPoint[0]), String.valueOf(stationLocationPoint[1]) + "," + String.valueOf(stationLocationPoint[0]), waypoints);
        if(routes.size()==1){
            List<LocationPoint> route = routes.get(0);
            if (route != null) {
                Transfer_path transfer_path = new Transfer_path();
                transfer_path.setTransfer_id(transfer_id);
                //path_num可以先查询当前transfer_id对应的路径数，由于下标从0开始，查询的路径数就是新的num值
                int num = transfer_pathMapper.countById(transfer_id);
                transfer_path.setPath_num(num);
                transfer_path.setPath_info(route.toString());
                //新增路径保存到transfer_path表
                int count = transfer_pathMapper.insert(transfer_path);
                if(count==1){
                    transfer.setPath_choice(num);
                    //transfer表中修改path_choice为新路径对应的num
                    int count2 = transferMapper.updateByPrimaryKey(transfer);
                    if(count2==1)
                        return "success";
                }
            }
        }
        return "fail";
    }

    @Override
    public String sure(String transfer_id) {
        //修改调拨状态
        Transfer transfer = transferMapper.selectByPrimaryKey(transfer_id);
        if("调度中".equals(transfer.getTransfer_status())){
            transfer.setTransfer_status("已调度");
            int count = transferMapper.updateByPrimaryKey(transfer);
            if(count!=1) return "fail";
        }
        //修改订单状态
        Order order = orderMapper.selectByPrimaryKey(transfer.getOrder_id());
        if("调度中".equals(order.getOrder_status())){
            order.setOrder_status("已调度");
            int count = orderMapper.updateByPrimaryKey(order);
            if(count!=1) return "fail";
        }
        //修改任务状态（可以直接点击调拨管理的确定按钮，但是这个确定相当于最终确定，点击之后无法进行任何调度相关的修改操作）
        Task task = taskMapper.selectByOrderId(order.getOrder_id());
        if("调度中".equals(task.getTask_status())){
            task.setTask_status("已调度");
            int count = taskMapper.updateByPrimaryKey(task);
            if(count!=1) return "fail";
        }
        return "success";
    }

    @Override
    public Integer getPathChoice(String transfer_id) {
        return transferMapper.selectByPrimaryKey(transfer_id).getPath_choice();
    }
}
